/**
 * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}}
 */
{{#description}}
@ApiModel(description = "{{{description}}}")
{{/description}}
{{#jackson}}
@JsonPropertyOrder({
  {{#vars}}
  {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
  {{/vars}}
})
@JsonTypeName("{{name}}")
{{/jackson}}
{{#additionalModelTypeAnnotations}}
{{{.}}}
{{/additionalModelTypeAnnotations}}
{{>generatedAnnotation}}{{#discriminator}}{{>model/typeInfoAnnotation}}{{/discriminator}}{{>model/xmlAnnotation}}{{#useBeanValidation}}
@Introspected
{{/useBeanValidation}}{{!
Declare the class with extends and implements
}}public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
    {{#serializableModel}}
  private static final long serialVersionUID = 1L;

    {{/serializableModel}}
    {{#vars}}
        {{#isEnum}}
            {{^isContainer}}
{{>model/modelInnerEnum}}
            {{/isContainer}}
            {{#isContainer}}
                {{#mostInnerItems}}
{{>model/modelInnerEnum}}
                {{/mostInnerItems}}
            {{/isContainer}}
        {{/isEnum}}
  public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
        {{#withXml}}
            {{#isXmlAttribute}}
  @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"
            {{/isXmlAttribute}}
            {{^isXmlAttribute}}
                {{^isContainer}}
  @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
                {{/isContainer}}
                {{#isContainer}}
  // Is a container wrapped={{isXmlWrapped}}
                    {{#items}}
  // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}}
  // items.example={{example}} items.type={{dataType}}
  @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
                    {{/items}}
                    {{#isXmlWrapped}}
  @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
                    {{/isXmlWrapped}}
                {{/isContainer}}
            {{/isXmlAttribute}}
        {{/withXml}}
        {{#vendorExtensions.x-is-jackson-optional-nullable}}
            {{#isContainer}}
  private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
            {{/isContainer}}
            {{^isContainer}}
  private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
            {{/isContainer}}
        {{/vendorExtensions.x-is-jackson-optional-nullable}}
        {{^vendorExtensions.x-is-jackson-optional-nullable}}
            {{#isContainer}}
  private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}};
            {{/isContainer}}
            {{^isContainer}}
  {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
            {{/isContainer}}
        {{/vendorExtensions.x-is-jackson-optional-nullable}}

    {{/vars}}
    {{#parcelableModel}}
  public {{classname}}() {
        {{#parent}}
    super();
        {{/parent}}
  }

    {{/parcelableModel}}
    {{#vars}}
        {{^isReadOnly}}
  public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
            {{#vendorExtensions.x-is-jackson-optional-nullable}}
    this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
            {{^vendorExtensions.x-is-jackson-optional-nullable}}
    this.{{name}} = {{name}};
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
    return this;
  }

            {{#isArray}}
  public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
                {{#vendorExtensions.x-is-jackson-optional-nullable}}
    if (this.{{name}} == null || !this.{{name}}.isPresent()) {
      this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}});
    }
    try {
      this.{{name}}.get().add({{name}}Item);
    } catch (java.util.NoSuchElementException e) {
      // this can never happen, as we make sure above that the value is present
    }
    return this;
                {{/vendorExtensions.x-is-jackson-optional-nullable}}
                {{^vendorExtensions.x-is-jackson-optional-nullable}}
                    {{^required}}
    if (this.{{name}} == null) {
      this.{{name}} = {{{defaultValue}}};
    }
                    {{/required}}
    this.{{name}}.add({{name}}Item);
    return this;
                {{/vendorExtensions.x-is-jackson-optional-nullable}}
  }

            {{/isArray}}
            {{#isMap}}
  public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
                {{#vendorExtensions.x-is-jackson-optional-nullable}}
    if (this.{{name}} == null || !this.{{name}}.isPresent()) {
      this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}});
    }
    try {
      this.{{name}}.get().put(key, {{name}}Item);
    } catch (java.util.NoSuchElementException e) {
      // this can never happen, as we make sure above that the value is present
    }
    return this;
                {{/vendorExtensions.x-is-jackson-optional-nullable}}
                {{^vendorExtensions.x-is-jackson-optional-nullable}}
                    {{^required}}
    if (this.{{name}} == null) {
      this.{{name}} = {{{defaultValue}}};
    }
                    {{/required}}
    this.{{name}}.put(key, {{name}}Item);
    return this;
                {{/vendorExtensions.x-is-jackson-optional-nullable}}
  }

            {{/isMap}}
        {{/isReadOnly}}
  /**
  {{#description}}
   * {{description}}
  {{/description}}
  {{^description}}
   * Get {{name}}
  {{/description}}
  {{#minimum}}
   * minimum: {{minimum}}
  {{/minimum}}
  {{#maximum}}
   * maximum: {{maximum}}
  {{/maximum}}
   * @return {{name}}
   **/
{{>model/beanValidation}}  @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
        {{#vendorExtensions.x-extra-annotation}}
  {{{vendorExtensions.x-extra-annotation}}}
        {{/vendorExtensions.x-extra-annotation}}
        {{#vendorExtensions.x-is-jackson-optional-nullable}}
{{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}  @JsonIgnore
        {{/vendorExtensions.x-is-jackson-optional-nullable}}
        {{^vendorExtensions.x-is-jackson-optional-nullable}}
            {{#jackson}}
{{>model/jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}}  public {{{datatypeWithEnum}}} {{getter}}() {
        {{#vendorExtensions.x-is-jackson-optional-nullable}}
            {{#isReadOnly}}
{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}}    if ({{name}} == null) {
      {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
    }
    {{/isReadOnly}}
    return {{name}}.orElse(null);
        {{/vendorExtensions.x-is-jackson-optional-nullable}}
        {{^vendorExtensions.x-is-jackson-optional-nullable}}
    return {{name}};
        {{/vendorExtensions.x-is-jackson-optional-nullable}}
  }

        {{#vendorExtensions.x-is-jackson-optional-nullable}}
{{>model/jackson_annotations}}
  public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
    return {{name}};
  }

  @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
  {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
    {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}   this.{{name}} = {{name}};
  }

        {{/vendorExtensions.x-is-jackson-optional-nullable}}
        {{^isReadOnly}}
            {{#jackson}}
                {{^vendorExtensions.x-is-jackson-optional-nullable}}
{{>model/jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}}  public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
            {{#vendorExtensions.x-is-jackson-optional-nullable}}
    this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
            {{^vendorExtensions.x-is-jackson-optional-nullable}}
    this.{{name}} = {{name}};
            {{/vendorExtensions.x-is-jackson-optional-nullable}}
  }

        {{/isReadOnly}}
    {{/vars}}
  @Override
  public boolean equals(Object o) {
    {{#useReflectionEqualsHashCode}}
    return EqualsBuilder.reflectionEquals(this, o, false, null, true);
    {{/useReflectionEqualsHashCode}}
    {{^useReflectionEqualsHashCode}}
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
        {{#hasVars}}
    {{classname}} {{classVarName}} = ({{classname}}) o;
    return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
        {{/-last}}{{/vars}}{{#parent}} &&
        super.equals(o){{/parent}};
        {{/hasVars}}
        {{^hasVars}}
    return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};
        {{/hasVars}}
    {{/useReflectionEqualsHashCode}}
  }

  @Override
  public int hashCode() {
    {{#useReflectionEqualsHashCode}}
    return HashCodeBuilder.reflectionHashCode(this);
    {{/useReflectionEqualsHashCode}}
    {{^useReflectionEqualsHashCode}}
    return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}});
    {{/useReflectionEqualsHashCode}}
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("class {{classname}} {\n");
    {{#parent}}
    sb.append("    ").append(toIndentedString(super.toString())).append("\n");
    {{/parent}}
    {{#vars}}
    sb.append("    {{name}}: ").append(toIndentedString({{name}})).append("\n");
    {{/vars}}
    sb.append("}");
    return sb.toString();
  }

  /**
   * Convert the given object to string with each line indented by 4 spaces
   * (except the first line).
   */
  private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) {
    if (o == null) {
      return "null";
    }
    return o.toString().replace("\n", "\n    ");
  }

    {{#parcelableModel}}
  public void writeToParcel(Parcel out, int flags) {
        {{#model}}
            {{#isArray}}
    out.writeList(this);
            {{/isArray}}
            {{^isArray}}
                {{#parent}}
    super.writeToParcel(out, flags);
                {{/parent}}
                {{#vars}}
    out.writeValue({{name}});
                {{/vars}}
            {{/isArray}}
        {{/model}}
  }

  {{classname}}(Parcel in) {
        {{#isArray}}
    in.readTypedList(this, {{arrayModelType}}.CREATOR);
        {{/isArray}}
        {{^isArray}}
            {{#parent}}
    super(in);
            {{/parent}}
            {{#vars}}
                {{#isPrimitiveType}}
    {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
                {{/isPrimitiveType}}
                {{^isPrimitiveType}}
    {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
                {{/isPrimitiveType}}
            {{/vars}}
        {{/isArray}}
  }

  public int describeContents() {
    return 0;
  }

  public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
    public {{classname}} createFromParcel(Parcel in) {
        {{#model}}
            {{#isArray}}
      {{classname}} result = new {{classname}}();
      result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
      return result;
            {{/isArray}}
            {{^isArray}}
      return new {{classname}}(in);
            {{/isArray}}
        {{/model}}
    }
    public {{classname}}[] newArray(int size) {
      return new {{classname}}[size];
    }
  };
    {{/parcelableModel}}
}